﻿using ModelLayer;
using ModelLayer.DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataRepositoryLayer.Interfaces
{
    public interface IBatteryRepository : IGenericDataRepository<Battery>
    {
        /// <summary>
        /// Retrieves battery data from the database, that matches provided data.
        /// </summary>
        /// <param name="desiredReservations">A list of all points on the route with corresponding data(time of reservation, distances).</param>
        /// <param name="currentReservations">A list of reservations that match desired type and points on the route.</param>
        /// <param name="desiredType">The type of battery to reserve.</param>
        /// <returns>All batteries to reserve with corresponding data.</returns>
        IList<Battery> GetPossibleBatteriesToReserve(IList<PointReservationDTO> desiredReservations, BatteryType desiredType);

        Battery GetByIdForReservation(int id);
    }

    public interface IBatteryReservationRepository : IGenericDataRepository<BatteryReservation>
    {
        /// <summary>
        /// Gather all battery reservations that match the data in the provided list.
        /// </summary>
        /// <param name="routePoints">List containing all points on the route that is to be reserved.</param>
        /// <returns>List of battery reservations that match requirements.</returns>
        IList<BatteryToReserveDTO> GetReservationsOnRoute(IList<PointReservationDTO> desiredReservations, IList<Battery> possibleBatteriesToReserve,
           BatteryType desiredType);

        bool TryToReserveSingle(Battery battery, BatteryType type);

        IList<BatteryReservation> GetCurrentReservations();

        IList<BatteryReservation> GetCurrentReservations(Station station);
    }


    public interface IBatteryTypeRepository : IGenericDataRepository<BatteryType>
    {
        /// <summary>
        /// Finds battery type with provided id, locks the database with ROWLOCK and XLOCK to prevent dirty reads while making a reservation
        /// The lock will prevent all SELECT statements from reading locked data assuming they will also use a lock (NOLOCK SELECTs will still work though)
        /// </summary>
        /// <param name="id">Id of the BatteryType to retrieve</param>
        /// <returns>BatteryType with provided id or null if nothing was found</returns>
        BatteryType GetByIdWithRowlock(int id);

        BatteryType GetById(int id);

        IList<BatteryType> GetAllForManagementSystem();

    }

    public interface IStationRepository : IGenericDataRepository<Station>
    {
        /// <summary>
        /// Retrieves all stations from the database for graph creation. Includes Pricings so they can be later used while creating a graph.
        /// </summary>
        /// <returns>All stations with Pricings included.</returns>
        IList<Station> GetAllForGraph();

        IList<Station> GetRouteStations(IList<Station> desiredStations);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id">If of desired station</param>
        /// <returns>Station with desired id or null if not found</returns>
        Station GetByIdWithBatteries(int id);
    }

    public interface IRouteReservationRepository : IGenericDataRepository<RouteReservation>
    {
        /// <summary>
        /// Reserves a route with provided data.
        /// </summary>
        /// <param name="batteriesToReserve">Batteries to reserve with dates of their reservation 
        /// and estimated distances traveled before the battery is reserved.</param>
        /// <param name="type">Type of batteries to reserve</param>
        /// <param name="userAccount">Account of user who makes the reservation</param>
        void ReserveRoute(IList<BatteryToReserveDTO> batteriesToReserve, BatteryType type, UserAccount userAccount);

        IList<RouteReservation> GetUserReservations(UserAccount account);
        
    }

    public interface IUserAccountRepository : IGenericDataRepository<UserAccount>
    {
        UserAccount CheckSessionToken(string sessionToken);

        UserAccount GetByUsername(string username);

        IList<UserAccount> GetForManagementSystem();

        UserAccount CheckEmailToken(string sessionToken);

        bool IsUsernameTaken(UserAccount account);
    }

    public interface IEmployeeAccountRepository : IGenericDataRepository<EmployeeAccount>
    {

        EmployeeAccount GetByUsername(string username);

        EmployeeAccount CheckSessionToken(string token);

        IList<EmployeeAccount> GetAllAccountsForManagementSystem();


        EmployeeAccount GetById(int id);
    }

    public interface IPricingRepository : IGenericDataRepository<Pricing>
    {

    }
}
